package de.szut.sudoku.game.field;

import java.util.ArrayList;

/**
 * Class for each group on the field
 * 
 * @author Marc Huisinga
 * 
 */
public class FieldGroup {
	private ArrayList<Box> boxes;

	public ArrayList<Box> getBoxes() {
		return boxes;
	}

	public void setBoxes(ArrayList<Box> boxes) {
		this.boxes = boxes;
	}

	public void addBox(Box box) {
		boxes.add(box);
	}

	public void deleteBox(Box box) {
		boxes.remove(box);
	}

	public Box getBoxFromIndex(int index) {
		return boxes.get(index);
	}

	/**
	 * Gets the available states of this fieldgroup
	 * 
	 * @return
	 */
	public int[] getStates() {
		int[] states = new int[boxes.size()];
		int index = 0;
		for (Box currentBox : boxes) {
			states[index] = currentBox.getState();
			index++;
		}
		return states;
	}

	/**
	 * Gets the available states of this fieldgroup without duplicates
	 * 
	 * @return
	 */
	public int[] getStatesWithoutDuplicates() {
		ArrayList<Integer> states = new ArrayList<Integer>();

		// gets the states without duplicates of all boxes in this fieldgroup
		for (Box currentBox : boxes) {
			if (!states.contains(currentBox.getState())
					&& currentBox.getState() != 0) {
				states.add(currentBox.getState());
			}
		}

		// converts the Integer ArrayList to an int array
		Integer[] integerEndStates = new Integer[states.size()];
		integerEndStates = states.toArray(integerEndStates);
		int[] endStates = new int[integerEndStates.length];
		int index = 0;
		for (Integer currentInteger : integerEndStates) {
			endStates[index] = currentInteger;
			index++;
		}
		return endStates;
	}

	/**
	 * Returns if the fieldgroup contains the box
	 * 
	 * @param box
	 * @return
	 */
	public boolean containsBox(Box box) {
		if (boxes.contains(box)) {
			return true;
		}
		return false;
	}

	/**
	 * Returns if the fieldgroup contains the value
	 * 
	 * @param value
	 * @return
	 */
	public boolean containsValue(int value) {
		for (Box currentBox : boxes) {
			if (currentBox.getState() == value) {
				return true;
			}
		}
		return false;
	}

	public int getIndexOfBox(Box box) {
		return boxes.indexOf(box);
	}

	/**
	 * gets the karthesian product of all states in an array of field groups
	 * 
	 * @param fieldGroups
	 * @return
	 */
	public static int[] getKarthesianStateProductOfFieldGroups(
			FieldGroup[] fieldGroups) {
		ArrayList<Integer> states = new ArrayList<Integer>();

		// Gets the states of the first group
		for (int currentInt : fieldGroups[0].getStatesWithoutDuplicates()) {
			states.add(currentInt);
		}

		// Creates the karthesian product by iterating through every fieldgroup,
		// getting the states and then adding the new states to the list
		for (int fieldGroupIndex = 1; fieldGroupIndex < fieldGroups.length; fieldGroupIndex++) {
			int[] currentStates = fieldGroups[fieldGroupIndex]
					.getStatesWithoutDuplicates();
			for (int currentInt : currentStates) {
				if (!states.contains(currentInt)) {
					states.add(currentInt);
				}
			}
		}

		// Converts the Integer ArrayList to an int array
		Integer[] integerEndStates = new Integer[states.size()];
		integerEndStates = states.toArray(integerEndStates);
		int[] endStates = new int[integerEndStates.length];
		int index = 0;
		for (Integer currentInteger : integerEndStates) {
			endStates[index] = currentInteger;
			index++;
		}

		return endStates;
	}

	public FieldGroup() {
		boxes = new ArrayList<Box>();
	}

	/**
	 * Clones the FieldGroup
	 */
	public FieldGroup clone() {
		FieldGroup clone = new FieldGroup();
		ArrayList<Box> clonedBoxes = new ArrayList<Box>();
		for (Box currentBox : boxes) {
			clonedBoxes.add(currentBox.clone());
		}
		clone.setBoxes(clonedBoxes);
		return clone;
	}

	/**
	 * Checks if the FieldGroup equals another FieldGroup
	 * 
	 * @param comp
	 * @return
	 */
	public boolean deepEquals(FieldGroup comp) {
		int index = 0;
		for (Box currentBox : boxes) {
			if (!currentBox.deepEquals(comp.getBoxes().get(index))) {
				return false;
			}
			index++;
		}
		return true;
	}
}
